#include "TwoMachineDebugging.h"

NTSTATUS TwoMachineDebugging::Start_TwoMachineDebugging(PDRIVER_OBJECT pPDriverObj)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	m_Hook.Hook_Init();
	Pass_TP_Security_Component();
	Status = Pass_TP_KdCom_Hook(pPDriverObj);
	Status = Pass_TP_anomaly();
    Pass_TP_KdDebuggerEnabled_Set_0();
	return Status;
    //NTSTATUS 定义为32位的无符号长整型。一般为返回值
   //::"::"在C++中表示作用域，和所属关系 表示作用域，和所属关系。

//::是运算符中等级最高的，它分为三种:

//1)global scope(全局作用域符），用法（::name)

//2)class scope(类作用域符），用法(class::name)

//3)namespace scope(命名空间作用域符），用法(namespace::name)
//
//他们都是左关联（left-associativity)

}

VOID TwoMachineDebugging::End_TwoMachineDebugging()
{
	SharedUserData->KdDebuggerEnabled = TRUE;
	if (this->m_IsHOOK) {
		m_Hook.UnhookKernelApi((PVOID)m_KdpTrap, m_KdpTrapBytes, m_patch_size);
	}
	
	m_Hook.Un_HookClass();
	KeCancelTimer(&g_PassObjTimer);
    //void中文翻译为“无类型”。常用在程序编写中对定义函数的参数类型、返回值、函数中指针类型进行声明。
//void的字面意思是“无类型”，void *则为“无类型指针”，void *可以指向任何类型的数据。

//“->”是C语言和C++语言的一个运算符，叫做指向结构体成员运算符，用处是使用一个指向结构体或对象的指针访问其内成员。
//this 只能用在类的内部，通过 this 可以访问类的所有成员，包括 private、protected、public 属性的
//这里的.不知道什么意思

    

}

VOID TwoMachineDebugging::Pass_TP_Security_Component()
{
	SharedUserData->KdDebuggerEnabled = FALSE;
    //Component组成部分 Security 安全
}

NTSTATUS TwoMachineDebugging::Pass_TP_KdCom_Hook(PDRIVER_OBJECT pPDriverObj)
{
	return FastFunction::HideDriver("kdcom.dll", pPDriverObj);
    ////NTSTATUS 定义为32位的无符号长整型。一般为返回值
}

NTSTATUS TwoMachineDebugging::Pass_TP_anomaly()
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	m_KdpTrap = Get_KdpTrapAddr();
	if (m_KdpTrap == 0) {
		return Status;
	}
	Status = HookKdpTrap(this->m_KdpTrap);
	return Status;
	//anomaly 异常
}

ULONGLONG TwoMachineDebugging::Get_KdpTrapAddr()
{

	ULONGLONG ntoskrnBaseAddr = FastFunction::GetSystemModuleBase("ntoskrnl.exe");
	/*
	   1803 8192CC
	   1803  = 0x8082CC
	*/
	ULONGLONG OffSet = 0x8192CC;
	return ntoskrnBaseAddr + OffSet;
}
NTSTATUS TwoMachineDebugging::HookedKdpTrap(
	IN PKTRAP_FRAME TrapFrame,
	IN PKEXCEPTION_FRAME ExceptionFrame,
	IN PEXCEPTION_RECORD ExceptionRecord,
	IN PCONTEXT ContextRecord,
	IN KPROCESSOR_MODE PreviousMode,
	IN BOOLEAN SecondChanceException
) 
{

	PEPROCESS hp = PsGetCurrentProcess();
	if (!_stricmp((char *)PsGetProcessImageFileName(hp), "TASLogin.exe"))
	{
		return STATUS_SUCCESS;
	}

	return OriginalKdpTrap(TrapFrame, ExceptionFrame, ExceptionRecord, ContextRecord, PreviousMode, SecondChanceException);
}
NTSTATUS TwoMachineDebugging::HookKdpTrap(ULONGLONG KdpTrap)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	if (KdpTrap == 0) {
		return Status;
	}

	m_KdpTrapBytes = m_Hook.HookKernelApi((PVOID)KdpTrap, (PVOID)HookedKdpTrap, (PVOID*)&OriginalKdpTrap, &m_patch_size);
	if (m_KdpTrapBytes == NULL) {
		return Status;
	}
	m_IsHOOK = TRUE;
	Status = STATUS_SUCCESS;
	return Status;
}
VOID
PassObj(
	__in struct _KDPC  *Dpc,
	__in_opt PVOID  DeferredContext,
	__in_opt PVOID  SystemArgument1,
	__in_opt PVOID  SystemArgument2
)
{
	__try
	{
	
		*KdDebuggerEnabled = 0x1;
	}
	__except (1)
	{
		return;
	}
	KeSetTimer(&g_PassObjTimer, g_PassObjTime, &g_PassObjDpc);
	return;
}
VOID TwoMachineDebugging::Pass_TP_KdDebuggerEnabled_Set_0()
{
	
	g_PassObjTime.QuadPart = -10000;
	KeInitializeTimer(&g_PassObjTimer);
	KeInitializeDpc(&g_PassObjDpc, &PassObj, NULL);
	KeSetTimer(&g_PassObjTimer, g_PassObjTime, &g_PassObjDpc);
	
}


